package org.example.my_netty.boss;

import lombok.Data;
import org.example.my_netty.worker.MyWorkerGroup;

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


//boss工作组 监听端口 accept事件 把大channel交给worker去处理
@Data
public class MyBoss {

    private MyWorkerGroup workerGroup;

    private Selector selector;

    //执行单元 这里直接是线程池算了
    private ExecutorService executorService= Executors.newFixedThreadPool(1);


    //这个boss工作启动 把工作扔给执行单元 因为不能自己死循环
    public void start(int port) {
        try {
            if(selector == null){
                selector = Selector.open();
            }

            //服务器channel 注册到selector
            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.configureBlocking(false);//启用非阻塞模式
            ssc.bind(new InetSocketAddress("localhost", port));
            //监听服务器channel accept事件
            ssc.register(selector, SelectionKey.OP_ACCEPT);

            executorService.execute(() -> {
                try {
                    bossWork();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });

        }
        catch (Exception e) {
            e.printStackTrace();
        }

    }


    //boss的工作 循环处理大channel 事件
    private void bossWork() throws Exception {
        while (true) {
            //监听 阻塞等待时间触发
            selector.select();

            //此时有事件触发了 拿到
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                //拿到事件并移除
                SelectionKey key = iterator.next();
                iterator.remove();

                //根据触发的事件类型 做处理
                if (key.isAcceptable()) {
                    //accept事件 把这个交给worker去处理
                    onAccept(key);
                }

            }
        }
    }


    //处理accept事件  丢给worker 去处理 他要的是channel
    private void onAccept( SelectionKey key) {
        System.out.println("触发了accept事件 boss线程" + Thread.currentThread().getName());
        workerGroup.start(key);

    }
}
